Repository navigation
fix(agent-sdk): show local command replies whose response never streamed - #444
Conversation
- record the API response ID of the last top-level stream that began, so a completed assistant message can be correlated with a streamed response - show a complete top-level reply once when its response never streamed: Claude Code answers /rename, /color and /usage that way (measured on 2.1.296), so its text had no other carrier (srothgan#438) - keep SDK-owned context Markdown as before; subagent, error and uncorrelated messages stay out of the transcript - cover both directions in a bridge test that npm test runs, and describe the rule in the architecture's activity section and the commands page
… version - cite Claude Code 2.1.288, the version the pinned SDK bundles, where the reply shape was measured; it sends no system/local_command_output for /rename, /color, /usage or /context - show that a non-streaming fallback after a partial stream is shown in full under its own response ID, beside the partial deltas - show that SDK context usage Markdown still appears without a response ID, which is why the declared context_usage check stays
|
Hi @srothgan, this is ready for review whenever you have time. Before opening it I read CONTRIBUTING.md, AGENTS.md and
After opening, I added one commit from my own review:
The PR description now explains why the declared I couldn't apply labels. Per CONTRIBUTING, I think Could you check it on your end and merge it if it looks good? Happy to change anything you'd like done differently. |
…s-prs chore: make the fork exactly upstream plus PRs srothgan#444 and srothgan#445
|
I tried I'd like functional session-color highlighting as a separate follow-up. This PR makes |
Summary
/rename,/color,/usage, ...) with one complete top-level assistant message, and that message's API response never streams. The bridge now records the response ID of the last top-levelmessage_start. When a completed top-level message carries a response ID that never started a stream, the bridge shows its text once.parent_tool_use_id,error, the message ID). It does not use the undeclaredlocal_command_*fields.context_usagefield stays. A test shows that/contextMarkdown is still shown even when a message has no response ID.Why
On
main,/rename probe,/color blueand/usagerun in Claude Code, but nothing appears under the command in claude-rs. The reply exists only in that unstreamed message, which the bridge drops. This is the reply half of #438.The SDK declares
SDKLocalCommandOutputMessage(system/local_command_output), and the bridge already shows it. I checked whether Claude Code uses it for these commands. On Claude Code 2.1.288, the version the pinned SDK 0.3.288 bundles,/rename,/color,/usageand/contexteach produced exactly one complete assistant message, zero stream events and nolocal_command_outputmessage. So the declared message never carries these replies, and the unstreamed assistant message is their only carrier.Refs #438
Validation
Automated, on this branch (macOS 27.2, Apple Silicon, rustc 1.98.1 from nixpkgs rather than the CI toolchain):
cargo fmt --all -- --check,cargo fetch --locked: passcargo clippy --locked --all-targets --all-features -- -D warnings: pass. Five lints that are new in clippy 1.98 are allowed, becausemainfails them too:collapsible_match,manual_is_multiple_of,manual_is_variant_and,map_unwrap_or,while_let_loop.cargo test --locked --all-features: pass. The serialterminal_resizerun: pass.agent-sdk:npm run build,test,lint,knip,auditandquality:duplicates: pass. The new tests live insrc/bridge/message_handlers.test.ts, sonpm testruns them (see Notes). They cover:Manual: I drove the debug binary in tmux against the Claude Code bundled with the pinned SDK (2.1.288), running
/rename probeand then/color blue.Screen text,
main:This branch:
Notes
docs/src/architecture.mdanddocs/src/commands.md.maindrops. The partial deltas shown before the break stay above it; a test covers this.npm testrunsnode --test dist/**/*.test.jsundersh, where**is a single*. As a result,dist/bridge.test.jsanddist/bridge.contract.test.jsnever run, locally or in CI. That is 333 tests. Run by hand, the same 16 spawned-bridge tests fail onmainand on this branch. Reported separately as [Bug]: npm test skips bridge.test.js and bridge.contract.test.js, where 16 tests fail #446.@anthropic-ai/claude-agent-sdk0.3.288 already exposes.